/**
 * @file
 *
 * Modulo per la gestione delle immagini utilizzate dal programma.
 *
 * In questo file vengono gestite le immagini incluse in fase di compilazione
 * nell'eseguibile. \n
 * Le immagini inizialmente devono essere rese disponibili al programma
 * chiamando la funzione ::load_xpm_images ed in seguito possono essere
 * utilizzate chiamando le funzioni ::image_new_from_pix e ::image_set_from_pix.
 */

// Author: Adrian Sassatelli
// Copyright (c) 2014 Adrian Sassatelli


#include <gtk/gtk.h>
#include "xpm_images.h"
#include "common.h"
#include "debug.h"
#include "xpm_images_list.h"


/* -------------------------------------------------------------------------- */
/*    DICHIARAZIONI                                                           */
/* -------------------------------------------------------------------------- */

/**
 * Struttura delle immagini delle caselle della griglia.
 *
 * Raggruppa le immagini che hanno funzionalità e/o applicazioni simili.
 */
struct pix_image_button_s {
    GdkPixbuf *checked;
    GdkPixbuf *maybe;
    GdkPixbuf *normal;
    GdkPixbuf *pressed;

    GdkPixbuf *near1;
    GdkPixbuf *near2;
    GdkPixbuf *near3;
    GdkPixbuf *near4;
    GdkPixbuf *near5;
    GdkPixbuf *near6;
    GdkPixbuf *near7;
    GdkPixbuf *near8;

    GdkPixbuf *exploded;
    GdkPixbuf *mine;
    GdkPixbuf *mineerr;
};

/* -------------------------------------------------------------------------- */

/**
 * Struttura delle immagini numeriche per i contatori.
 *
 * Raggruppa le immagini che hanno funzionalità e/o applicazioni simili.
 */
struct pix_image_number_s {
    GdkPixbuf *number0;
    GdkPixbuf *number1;
    GdkPixbuf *number2;
    GdkPixbuf *number3;
    GdkPixbuf *number4;
    GdkPixbuf *number5;
    GdkPixbuf *number6;
    GdkPixbuf *number7;
    GdkPixbuf *number8;
    GdkPixbuf *number9;

    GdkPixbuf *number_sep1;
    GdkPixbuf *number_sep2;
};

/* -------------------------------------------------------------------------- */

/**
 * Struttura delle immagini per la visualizzazione dello stato della partita.
 *
 * Raggruppa le immagini che hanno funzionalità e/o applicazioni simili.
 */
struct pix_image_status_s {
    GdkPixbuf *lost;
    GdkPixbuf *normal;
    GdkPixbuf *win;
};

/* -------------------------------------------------------------------------- */

/** Variabile struttura delle immagini delle caselle della griglia. */
static pix_image_button_s pix_image_button;

/** Variabile struttura delle immagini, numeriche per i contatori. */
static pix_image_number_s pix_image_number;

/** Variabile struttura delle immagini per la visualizzazione dello stato della partita. */
static pix_image_status_s pix_image_status;


/* -------------------------------------------------------------------------- */
/*    FUNZIONI                                                                */
/* -------------------------------------------------------------------------- */

/* Crea un nuovo oggetto immagine partendo dalle immagini disponibile a runtime */
GtkImage *image_new_from_pix (const pix_image_e apixid) {
    return (GtkImage *) gtk_image_new_from_pixbuf (pixid_to_image (apixid));
}

/* -------------------------------------------------------------------------- */

/* Imposta l'immagine dell'oggetto partendo dalle immagini disponibile a runtime */
void image_set_from_pix (GtkImage *aimage, const pix_image_e apixid) {
    gtk_image_set_from_pixbuf (aimage, pixid_to_image (apixid));    // Imposta immagine
}

/* -------------------------------------------------------------------------- */

/**
 * Carica e ridimensione l'immagine.
 *
 * Legge l'immagina dall'eseguibile e la ridimensiona utilizzando il parametro
 * adim.
 *
 * @param[in] axpm Nome immagine
 * @param[in] adim Nuova dimensione
 * @return Oggetto immagine ridimensionato
 */
static GdkPixbuf *load_and_resize_xpm (const char *axpm[], const int adim) {
    GdkPixbuf *image;

    image = gdk_pixbuf_new_from_xpm_data ((const char **) axpm);    // Carica immagine
    image = gdk_pixbuf_scale_simple (image, adim, adim, GDK_INTERP_BILINEAR);    // Ridimensione immagine

    return image;
}

/* -------------------------------------------------------------------------- */

/* Rende disponibili al programma le immagini incluse in fase di compilazione */
void load_xpm_images () {
    DBG_FUNCNAME ("load_xpm_images", "carica immagini in memoria");

    // Sezione immagini relative alle caselle sulla griglia
    pix_image_button.checked = load_and_resize_xpm (button_checked_xpm, IMG_BUTTON_DIM);
    pix_image_button.maybe = load_and_resize_xpm (button_maybe_xpm, IMG_BUTTON_DIM);
    pix_image_button.normal = load_and_resize_xpm (button_normal_xpm, IMG_BUTTON_DIM);
    pix_image_button.pressed = load_and_resize_xpm (button_pressed_xpm, IMG_BUTTON_DIM);

    pix_image_button.near1 = load_and_resize_xpm (button_near1_xpm, IMG_BUTTON_DIM);
    pix_image_button.near2 = load_and_resize_xpm (button_near2_xpm, IMG_BUTTON_DIM);
    pix_image_button.near3 = load_and_resize_xpm (button_near3_xpm, IMG_BUTTON_DIM);
    pix_image_button.near4 = load_and_resize_xpm (button_near4_xpm, IMG_BUTTON_DIM);
    pix_image_button.near5 = load_and_resize_xpm (button_near5_xpm, IMG_BUTTON_DIM);
    pix_image_button.near6 = load_and_resize_xpm (button_near6_xpm, IMG_BUTTON_DIM);
    pix_image_button.near7 = load_and_resize_xpm (button_near7_xpm, IMG_BUTTON_DIM);
    pix_image_button.near8 = load_and_resize_xpm (button_near8_xpm, IMG_BUTTON_DIM);

    pix_image_button.exploded = load_and_resize_xpm (button_exploded_xpm, IMG_BUTTON_DIM);
    pix_image_button.mine = load_and_resize_xpm (button_mine_xpm, IMG_BUTTON_DIM);
    pix_image_button.mineerr = load_and_resize_xpm (button_mineerr_xpm, IMG_BUTTON_DIM);

    // Sezione immagini relative ai contatori
    pix_image_number.number0 = gdk_pixbuf_new_from_xpm_data ((const char **) number0_xpm);
    pix_image_number.number1 = gdk_pixbuf_new_from_xpm_data ((const char **) number1_xpm);
    pix_image_number.number2 = gdk_pixbuf_new_from_xpm_data ((const char **) number2_xpm);
    pix_image_number.number3 = gdk_pixbuf_new_from_xpm_data ((const char **) number3_xpm);
    pix_image_number.number4 = gdk_pixbuf_new_from_xpm_data ((const char **) number4_xpm);
    pix_image_number.number5 = gdk_pixbuf_new_from_xpm_data ((const char **) number5_xpm);
    pix_image_number.number6 = gdk_pixbuf_new_from_xpm_data ((const char **) number6_xpm);
    pix_image_number.number7 = gdk_pixbuf_new_from_xpm_data ((const char **) number7_xpm);
    pix_image_number.number8 = gdk_pixbuf_new_from_xpm_data ((const char **) number8_xpm);
    pix_image_number.number9 = gdk_pixbuf_new_from_xpm_data ((const char **) number9_xpm);

    pix_image_number.number_sep1 = gdk_pixbuf_new_from_xpm_data ((const char **) number_sep1_xpm);
    pix_image_number.number_sep2 = gdk_pixbuf_new_from_xpm_data ((const char **) number_sep2_xpm);

    // Sezione immagini relative allo stato della partita
    pix_image_status.lost = load_and_resize_xpm (status_lost_xpm, IMG_STATUS_DIM);
    pix_image_status.normal = load_and_resize_xpm (status_normal_xpm, IMG_STATUS_DIM);
    pix_image_status.win = load_and_resize_xpm (status_win_xpm, IMG_STATUS_DIM);
}

/* -------------------------------------------------------------------------- */

/* Restituisce l'immagine relativa all'id selezionato */
GdkPixbuf *pixid_to_image (const pix_image_e avalue) {
    switch (avalue) {
        // Sezione immagini relative alle caselle sulla griglia
        case PI_BUTTON_CHECKED: return pix_image_button.checked; break;
        case PI_BUTTON_MAYBE: return pix_image_button.maybe; break;
        case PI_BUTTON_NORMAL: return pix_image_button.normal; break;
        case PI_BUTTON_PRESSED: return pix_image_button.pressed; break;

        case PI_BUTTON_EXPLODED: return pix_image_button.exploded; break;
        case PI_BUTTON_MINE: return pix_image_button.mine; break;
        case PI_BUTTON_MINEERR: return pix_image_button.mineerr; break;

        case PI_BUTTON_NEAR1: return pix_image_button.near1; break;
        case PI_BUTTON_NEAR2: return pix_image_button.near2; break;
        case PI_BUTTON_NEAR3: return pix_image_button.near3; break;
        case PI_BUTTON_NEAR4: return pix_image_button.near4; break;
        case PI_BUTTON_NEAR5: return pix_image_button.near5; break;
        case PI_BUTTON_NEAR6: return pix_image_button.near6; break;
        case PI_BUTTON_NEAR7: return pix_image_button.near7; break;
        case PI_BUTTON_NEAR8: return pix_image_button.near8; break;

        // Sezione immagini relative ai contatori
        case PI_NUMBER0: return pix_image_number.number0; break;
        case PI_NUMBER1: return pix_image_number.number1; break;
        case PI_NUMBER2: return pix_image_number.number2; break;
        case PI_NUMBER3: return pix_image_number.number3; break;
        case PI_NUMBER4: return pix_image_number.number4; break;
        case PI_NUMBER5: return pix_image_number.number5; break;
        case PI_NUMBER6: return pix_image_number.number6; break;
        case PI_NUMBER7: return pix_image_number.number7; break;
        case PI_NUMBER8: return pix_image_number.number8; break;
        case PI_NUMBER9: return pix_image_number.number9; break;

        case PI_NUMBER_SEP1: return pix_image_number.number_sep1; break;
        case PI_NUMBER_SEP2: return pix_image_number.number_sep2; break;

        // Sezione immagini relative allo stato della partita
        case PI_STATUS_LOST: return pix_image_status.lost; break;
        case PI_STATUS_NORMAL: return pix_image_status.normal; break;
        case PI_STATUS_WIN: return pix_image_status.win; break;

        default: return NULL;
    }
}

/* -------------------------------------------------------------------------- */

/* Restituisce l'immagine della cifra relativa al parametro in ingresso */
void show_image_number (GtkImage *aimage, const int anum) {
//    DBG_FUNCNAME ("show_image_number", "restituisce immagine relativa a cifra");

    pix_image_e v = PI_NONE;

    switch (anum) {
        case 0: v = PI_NUMBER0; break;
        case 1: v = PI_NUMBER1; break;
        case 2: v = PI_NUMBER2; break;
        case 3: v = PI_NUMBER3; break;
        case 4: v = PI_NUMBER4; break;
        case 5: v = PI_NUMBER5; break;
        case 6: v = PI_NUMBER6; break;
        case 7: v = PI_NUMBER7; break;
        case 8: v = PI_NUMBER8; break;
        case 9: v = PI_NUMBER9; break;
        default: assert (false);    // Non possibile
    }

    image_set_from_pix (aimage, v);    // Imposta immagine
}

/* -------------------------------------------------------------------------- */

/* Libera la memoria dalle immagini */
void unload_xpm_images () {
    DBG_FUNCNAME ("unload_xpm_images", "libera memoria dalle immagini");

    // Sezione immagini relative alle caselle sulla griglia
    g_object_unref (pix_image_button.checked);
    g_object_unref (pix_image_button.maybe);
    g_object_unref (pix_image_button.normal);
    g_object_unref (pix_image_button.pressed);

    g_object_unref (pix_image_button.near1);
    g_object_unref (pix_image_button.near2);
    g_object_unref (pix_image_button.near3);
    g_object_unref (pix_image_button.near4);
    g_object_unref (pix_image_button.near5);
    g_object_unref (pix_image_button.near6);
    g_object_unref (pix_image_button.near7);
    g_object_unref (pix_image_button.near8);

    g_object_unref (pix_image_button.exploded);
    g_object_unref (pix_image_button.mine);
    g_object_unref (pix_image_button.mineerr);

    // Sezione immagini relative ai contatori
    g_object_unref (pix_image_number.number0);
    g_object_unref (pix_image_number.number1);
    g_object_unref (pix_image_number.number2);
    g_object_unref (pix_image_number.number3);
    g_object_unref (pix_image_number.number4);
    g_object_unref (pix_image_number.number5);
    g_object_unref (pix_image_number.number6);
    g_object_unref (pix_image_number.number7);
    g_object_unref (pix_image_number.number8);
    g_object_unref (pix_image_number.number9);

    g_object_unref (pix_image_number.number_sep1);
    g_object_unref (pix_image_number.number_sep2);

    // Sezione immagini relative allo stato della partita
    g_object_unref (pix_image_status.lost);
    g_object_unref (pix_image_status.normal);
    g_object_unref (pix_image_status.win);
}

/* -------------------------------------------------------------------------- */
